package com.jysz.certificate.service.mf;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Service;

import com.jysz.certificate.persistence.dao.cm.CertificationCoreDao;
import com.jysz.certificate.persistence.dao.mf.BillApplyDao;
import com.jysz.certificate.persistence.dao.mf.BillDao;
import com.jysz.certificate.persistence.dao.mf.BillOptionDao;
import com.jysz.certificate.persistence.dao.system.FinancialDao;
import com.jysz.certificate.persistence.dao.system.ShopDao;
import com.jysz.certificate.persistence.dao.system.TreatyDao;
import com.jysz.certificate.persistence.enums.mf.BillStatus;
import com.jysz.certificate.persistence.model.mf.Bill;
import com.jysz.certificate.persistence.model.mf.BillApply;
import com.jysz.certificate.persistence.model.mf.BillOption;
import com.jysz.certificate.persistence.model.system.Financial;
import com.jysz.certificate.persistence.model.system.Organization;
import com.jysz.certificate.persistence.model.system.Shop;
import com.jysz.certificate.persistence.model.system.Treaty;
import com.jysz.certificate.persistence.model.system.User;
import com.jysz.certificate.service.cm.CertificationService;
import com.jysz.certificate.service.system.OrganizationService;
import com.jysz.certificate.utils.CommonUtil;
import com.jysz.certificate.utils.DateUtil;
import com.jysz.webcore.ssh.orm.hibernate.support.Page;
import com.jysz.webcore.ssh.service.EntityService;

/**
 * 发票申请Service
 * @author xuxiaolong
 */
@Service
public class BillApplyService extends EntityService<BillApply, Long, BillApplyDao> {

	@Override
	public BillApplyDao getEntityDao() {
		return this.applyDao;
	}

	@Resource
	private BillApplyDao applyDao;
	@Resource
	private BillDao billDao;
	@Resource
	private BillOptionDao optionDao;
	@Resource
	private FinancialDao financialDao;
	@Resource
	private ShopDao shopDao;
	@Resource
	private TreatyDao treatyDao;
	@Resource
	private CertificationCoreDao certificationDao;
	@Resource
	private CertificationService cfService;
	@Resource
	private OrganizationService organizationService;
	@Resource
	private CertificationService certificationService;
	
	/**
	 * 发票申请 查询
	 * @author xuxiaolong
	 * @param search
	 */
	public Page<BillApply> findPage(BillApply search, int pageNo, int pageSize){
		
		Criteria criteria = applyDao.createCriteria();
		criteria.addOrder(Order.desc("applyDate"));
		if(search!=null){
			//发起人
			if(search.getApplyUser()!=null&&CommonUtil.isNotEmpty(search.getApplyUser().getRealName()))
				criteria.createCriteria("applyUser").add(Restrictions.like("realName", search.getApplyUser().getRealName(),MatchMode.ANYWHERE));
			//申请日期-开始
			if(search.getCreatedAt()!=null)
				criteria.add(Restrictions.ge("applyDate", search.getCreatedAt()));
			//申请日期-结束
			if(search.getUpdatedAt()!=null)
				criteria.add(Restrictions.le("applyDate", search.getUpdatedAt()));
		}
		return super.findPage(criteria, pageNo, pageSize);
		
	}

	@Resource
	private BillService billService;
	/**
	 * 新增开票申请--金融机构
	 * @throws ParseException 
	 */
	public BillApply createFinancial(User user) throws ParseException{
		String currentMonth=DateUtil.formatDate(new Date(), "yyyy-MM");
		int allcount=0;//记录新增了多少条option
		
		//申请单
		BillApply apply=new BillApply();
		apply.setStatus(BillStatus.TEMPSAVE);
		apply.setStatus(BillStatus.TEMPSAVE);
		apply.setApplyUser(user);
//		apply.setApplyDate(new Date());//新建时申请时间应为空
		apply.setApplyNum("金融机构   "+currentMonth);//申请批次号 需要生成规则
		apply.setShopFlag(false);
		this.save(apply);
		List<Bill> bills = new ArrayList<Bill>();//发票单
		List<Financial> financials = financialDao.financialBilling();//查询需要单独开票的金融机构
		if(null != financials && financials.size() > 0){//判断是否有需要独立开票的金融机构
			for(Financial financial : financials){
				Map<String, String> monthsMap = new HashMap<String, String>();//记录当前金融机构的开票月份
				String monthsReams = "" ;//记录
				Double sumMoney=0D;
				List<BillOption> billOptions = new ArrayList<BillOption>();//发票申请详单
				Bill bill = new Bill();
				bill.setStatus(BillStatus.TEMPSAVE);
				bill.setBillApply(apply);
				
				List<Treaty> treaties = treatyDao.treatyAppalys(financial.getId());//查询对应的协议
				if(null != treaties && treaties.size()>0){//判断是否存在协议
					bill.setFinancial(financial);
					billService.save(bill);
					for(Treaty treaty : treaties){//循环协议
//						bill.setShop(treaty.getShop());
						if(treaty.getFinancial().getId() == 8 && treaty.getShop().getId()==8){
							System.out.println(treaty.getFinancial().getId()+"----------"+treaty.getShop().getId());
						}
						if(treaty.getUnitPrice() == null || treaty.getUnitPrice()==0D){//单证释放价为零允许预收
							String months[]=getMonths(treaty,true);//查询该店铺、该金融机构 截止当前月，有多少个月没缴费(按季度3个月整)
							List<BillOption> errorOptions=getErrorMonthsFianl(treaty);//查找该店铺、该金融机构  之前的预收情况，看是否存在不该收费的。
							int errorSize=errorOptions==null?0:errorOptions.size();
							int errorCount=0;
							if(null != months){
								for(int i=0;i<months.length;i++){
									String  month=months[i];
									if(month.compareTo(currentMonth)>=0){//月份大于等于当月 预收
										if(errorCount<errorSize){//将之前不该收费的预收挪动到后面月份的预收
											BillOption old=errorOptions.get(errorCount);
											
											BillOption option=new BillOption();
											option.setBillsForOne(bill);
											option.setTreaty(treaty);//添加协议
											option.setShop(treaty.getShop());
											option.setFinancial(treaty.getFinancial());
											option.setMonth(old.getMonth());//将以前错误预收的月份添加到新单，金额为0
											option.setAmount(0D);//以前的错误预收金额更正为0
											option.setMoveId(old.getId());//记录从哪里挪动过来
											option.setOperate(1);
											option.setAdvance(false);//变更类型为应收。
											option.setStatus(old.getStatus());
											optionDao.save(option);//--
//											optionDao.getSession().flush();
											++allcount;
											billOptions.add(option);
											
											old.setMonth(month);//将以前的月份改为预收新月份
//											old.setFinancial(treaty.getFinancial());
											old.setRemark(old.getRemark()==null?"":old.getRemark()+" 此预收金额由"+option.getMonth()+"挪动过来");
											 
											optionDao.save(old);
											errorCount++;
										}else{//直接预收
											Double money=treaty.getFloors();
											if(treaty.getMaximum() != null && treaty.getMaximum()>0){//设置管理费的最大数
												if(money>treaty.getMaximum()){
													money = treaty.getMaximum();
												}
											}
											String defendName =findUserShopByShopName(treaty.getShop().getId());//获得驻店员的名字
											String managerName =findUserDomainByShopName(treaty.getShop().getId());//获得区域经理的名字
											int  quantity = cfService.findReleaseCertificationInMonth(treaty.getFinancial().getId(),treaty.getShop().getId(),month);//获得指定日期内的释放数
											int  moneyStock = cfService.findCertificationInMonthBill(treaty.getShop().getId(),treaty.getFinancial().getId(),month);//获得指定日期内的入库数
											int  moneyRemain = cfService.findBeforeCertifcatiionInQtyBill(treaty.getShop().getId(),treaty.getFinancial().getId(),month);//获得指定日期内的结存数
											BillOption option=new BillOption(treaty,treaty.getShop(),treaty.getFinancial(),month,money,currentMonth.equals(month)?true:false,null,defendName,managerName,quantity,moneyStock,moneyRemain);
											sumMoney+=money;
											 
											optionDao.save(option);//--
											++allcount;
											billOptions.add(option);
										}
									}else{//月份小于当前月,应收
										Double money=0D;
										if(checkFianl(treaty,month,financial.getIsOpenBill(),financial.getIsOpenmoneyStockBill(),financial.getIsOpenReleteBill())){
											//判断当月是否应该收费
											if(treaty.getFloors() == null){
												treaty.setFloors(0D);
											}
											money=treaty.getFloors();
											if(treaty.getMaximum() != null && treaty.getMaximum()>0){
												if(money>treaty.getMaximum()){//设置管理费的最大数
													money = treaty.getMaximum();
												}
											}
										}
											
											sumMoney+=money;
											String defendName =findUserShopByShopName(treaty.getShop().getId());//获得驻店员的名字
											String managerName =findUserDomainByShopName(treaty.getShop().getId());//获得区域经理的名字
											int  moneyStock = cfService.findCertificationInMonthBill(treaty.getShop().getId(),treaty.getFinancial().getId(),month);//获得指定日期内的入库数
											int  moneyRemain = cfService.findBeforeCertifcatiionInQtyBill(treaty.getShop().getId(),treaty.getFinancial().getId(),month);//获得指定日期内的结存数
											int  quantity = cfService.findReleaseCertificationInMonth(treaty.getFinancial().getId(),treaty.getShop().getId(),month);//获得指定日期内的释放数
										BillOption option=new BillOption(treaty,treaty.getShop(),treaty.getFinancial(),month,money,false,null,defendName,managerName,quantity,moneyStock,moneyRemain);
										 
										optionDao.save(option);//--
										++allcount;
										billOptions.add(option);
									}
									
								}
							}
						}else{
							String months[]=getMonths(treaty,false);//查询该店铺、该金融机构 截上个月，有多少个月没缴费
							if(null != months){
								for(String month:months){
									Double money=0D;
									if(checkFianl(treaty,month,financial.getIsOpenBill(),financial.getIsOpenmoneyStockBill(),financial.getIsOpenReleteBill())){//如果不该收费，金额为0
										if(treaty.getFloors() == null){
											treaty.setFloors(0D);
										}
										if(treaty.getUnitPrice() == null){
											treaty.setUnitPrice(0D);
										}
										int cfCount=cfService.findReleaseCertificationInMonth(treaty.getFinancial().getId(), treaty.getShop().getId(), month);//查询该月份、该店、该金融机构释放的证个数
										money=treaty.getFloors()+treaty.getUnitPrice()*cfCount;
										if(treaty.getMaximum() != null && treaty.getMaximum()>0){
											if(money>treaty.getMaximum()){//设置管理费的最大数
												money = treaty.getMaximum();
											}
										}
									}
									String defendName =findUserShopByShopName(treaty.getShop().getId());//获得驻店员的名字
									String managerName =findUserDomainByShopName(treaty.getShop().getId());//获得区域经理的名字
									int  moneyStock = cfService.findCertificationInMonthBill(treaty.getShop().getId(),treaty.getFinancial().getId(),month);//获得指定日期内的入库数
									int  moneyRemain = cfService.findBeforeCertifcatiionInQtyBill(treaty.getShop().getId(),treaty.getFinancial().getId(),month);//获得指定日期内的结存数
									int  quantity = cfService.findReleaseCertificationInMonth(treaty.getFinancial().getId(),treaty.getShop().getId(),month);//获得指定日期内的释放数
									BillOption option=new BillOption(treaty,treaty.getShop(),treaty.getFinancial(),month,money,false,null,defendName,managerName,quantity,moneyStock,moneyRemain);
									sumMoney+=money;
									 
									optionDao.save(option);//--
									++allcount;
									billOptions.add(option);
								}
							}
							
						}
						
						
					}
//					bill.setBillRemark(financial.getBrief()+":"+monthsReams+" "+sumMoney);
					bill.setReceivableAmount(sumMoney);
					bill.setPaymentName(financial.getName());
					bill.setFinancial(financial);
					bill.setApplyDate(new Date());
					bill.setOptions(billOptions);
					bill.setShop(null);
					bills.add(bill);
				}
			}
			apply.setBills(bills);
			applyDao.save(apply);
//			return apply;
			if(allcount>0){
				return apply;
			}else{
				applyDao.destory(apply);
				return null;
				
			}
		}
		return null;
	}
	
	/**
	 *@author xuxiaolong
	 * 新增开票申请
	 *  默认所有店都不需要单独开票 
	 * @throws ParseException
	 */
	public BillApply create(User user) throws ParseException{
		String currentMonth=DateUtil.formatDate(new Date(), "yyyy-MM");
		//申请单
		BillApply apply=new BillApply();
		apply.setShopFlag(true);
		apply.setApplyUser(user);
//		apply.setApplyDate(new Date());
		apply.setApplyNum("店  "+currentMonth);//根据申请次数生成
		apply.setStatus(BillStatus.TEMPSAVE);
		
		//发票集合
		List<Bill> billList=new ArrayList<Bill>();
		int allcount=0;//记录新增了多少条option
		
		List<Shop> shops=shopDao.findByEnabledTreaty();//获取有生效协议的店铺
		for(Shop shop:shops){
			int shopcount=0;
			Double sumMoney=0D;
			Bill bill=new Bill();
			bill.setStatus(BillStatus.TEMPSAVE);
			bill.setPaymentName(shop.getCompany());
			bill.setBillApply(apply);
			bill.setShop(shop);
			bill.setApplyDate(new Date());//.添加申请时间
			
			List<Treaty> treatyList=treatyDao.treatyListByBilling(shop.getId(),"1");//查找店铺签订的所有协议
			if(CommonUtil.isEmptyList(treatyList))
				continue;
			List<BillOption> optionList=new ArrayList<BillOption>();
			for(Treaty treaty:treatyList){
				
				//单证释放价为0，允许预收.生成月份包含当月
				if(treaty.getUnitPrice() == null || treaty.getUnitPrice()==0){
					String months[]=getMonths(treaty, true);//查询该店铺、该金融机构 截止当前月，有多少个月没缴费(按季度3个月整)
					List<BillOption> errorOptions=getErrorMonths(treaty);//查找该店铺、该金融机构  之前的预收情况，看是否存在不该收费的。
					int errorSize=errorOptions==null?0:errorOptions.size();
					int errorCount=0;
					
					if(months != null){
						for(int i=0;i<months.length;i++){
							String  month=months[i];
							if(month.compareTo(currentMonth)>=0){//月份大于等于当月 预收
								if(errorCount<errorSize){//将之前不该收费的预收挪动到后面月份的预收
									BillOption old=errorOptions.get(errorCount);
									
									BillOption option=new BillOption();
									//option.setBillsForOne(bill);
									option.setTreaty(treaty);//添加协议
									option.setShop(shop);
									option.setFinancial(treaty.getFinancial());
									option.setMonth(old.getMonth());//将以前错误预收的月份添加到新单，金额为0
									option.setAmount(0D);//以前的错误预收金额更正为0
									option.setMoveId(old.getId());//记录从哪里挪动过来
									option.setOperate(1);
									option.setAdvance(false);//变更类型为应收。
									option.setStatus(old.getStatus());
									optionDao.save(option);//--
									allcount++;
									shopcount++;
									optionList.add(option);
									
									old.setMonth(month);//将以前的月份改为预收新月份
									old.setOperate(2);//挪动的金额不允许再编辑
									old.setRemark(old.getRemark()==null?"":old.getRemark()+" 此预收金额由"+option.getMonth()+"挪动过来");
									optionDao.save(old);
									errorCount++;
								}else{//直接预收
									Double money=treaty.getFloors();
									BillOption option=new BillOption(treaty,shop,treaty.getFinancial(),month,money,currentMonth.equals(month)?true:false,null,null,null,0,0,0);
									optionDao.save(option);//--
									allcount++;
									shopcount++;
									sumMoney+=money;
									optionList.add(option);
								}
							}else{//月份小于当前月,应收
								Double money=0D;
								if(check(treaty,month))//判断当月是否应该收费
									money=treaty.getFloors();
								BillOption option=new BillOption(treaty,shop,treaty.getFinancial(),month,money,false,null,null,null,0,0,0);
								optionDao.save(option);//--
								allcount++;
								shopcount++;
								sumMoney+=money;
								optionList.add(option);
							}
							
						}
					}
				}
				//单证释放价不为0，不允许预收.生成月份截止上个月.
				else{
					String months[]=getMonths(treaty, false);//查询该店铺、该金融机构 截上个月，有多少个月没缴费
					if(null != months){
						double tmp=0.0;//用于发票备注
						for(String month:months){
							Double money=0D;
							if(check(treaty,month)){//如果不该收费，金额为0
								if(treaty.getFloors() == null){//
									treaty.setFloors(0D);
								}
								if(treaty.getUnitPrice() == null){
									treaty.setUnitPrice(0D);
								}
								int cfCount=cfService.findReleaseCertificationInMonth(treaty.getFinancial().getId(), treaty.getShop().getId(), month);//查询该月份、该店、该金融机构释放的证个数
								money=treaty.getFloors()+treaty.getUnitPrice()*cfCount;
							}
							BillOption option=new BillOption(treaty,shop,treaty.getFinancial(),month,money,false,null,null,null,0,0,0);
							optionDao.save(option);//--
							allcount++;
							shopcount++;
							sumMoney+=money;
							optionList.add(option);
						}
					}
					
				}
				
			}
			if(shopcount>0){
				bill.setOptions(optionList);
				bill.setReceivableAmount(sumMoney);//发票的应收总金额
				billList.add(bill);
			}
		}
		if(allcount>0)
			apply.setBills(billList);
		
		super.save(apply);
		return apply;
	}
	
	/**
	 * 获得预收月份
	 * @param financialId
	 * @param shopId
	 * @return
	 */
	public List<String> findAdvanceMonths(Long financialId,Long shopId){
		return optionDao.findAdvanceMonths(financialId, shopId);
	}
	
	/**
	 * 获得店铺指定月份的预收情况
	 * @param shopId
	 * @return
	 */
	public List<BillOption> findCurrentMonthAdvance(Long shopId,String month){
		
//		String currentMonth=DateUtil.formatDate(new Date(), "yyyy-MM");
		return optionDao.findAdvanceOption(shopId, month);
		 
	}
	
	/**
	 * 获得店铺指定月份的预收情况
	 * @param shopId
	 * @return
	 */
	public List<BillOption> findCurrentMonthAdvance(Long finId,String month,Long billId){
		
		return optionDao.findAdvanceOption(finId,month,billId);
		
	}
	
	//检查重复的发票明细
	public int checkMonth(Long financialId, Long shopId,String month){
		List<BillOption>list= optionDao.findAdvanceMonths(financialId, shopId,month);
		if(list!=null)
			return list.size();
		return 0;
	}
	
	/**
	 * 提交申请开票
	 * @author xuxiaolong
	 * @param ids 需要单独开票的发票ID
	 * @param apply
	 */
	public void submit(BillApply apply,List<Long> ids,List<Long>idmons){
		
		List<Bill> bills = apply.getBills();
		
		if(ids != null){
			List<Bill> delBills=new ArrayList<Bill>();
			List<Bill> newBills=new ArrayList<Bill>();
			
			for(Bill bill : bills){
				if(bill.getOptions()==null||bill.getOptions().size()==0){//删除空发票
					delBills.add(bill);
					bill.setOptions(null);
					billDao.destory(bill);
				}else{
					bill.setApplyDate(new Date());
					// 仅需要独立开票的发票
					if(containsId(ids,bill.getId())&&!containsId(idmons,bill.getId())){
						//根据金融机构分类
						Map<Financial,List<BillOption>> map=new HashMap<Financial, List<BillOption>>();
						for(BillOption bo:bill.getOptions()){
							if(map.containsKey(bo.getFinancial())){
								map.get(bo.getFinancial()).add(bo);
							}else{
								List<BillOption> options = new ArrayList<BillOption>();
								options.add(bo);
								map.put(bo.getFinancial(), options);
							}
						}
						Bill tmp;
						
						//循环添加
						if(map.size() > 1){
							for(Financial fin : map.keySet() ){
								tmp = new Bill(bill, map.get(fin));
								newBills.add(tmp);
							}
							
							//删除Bill
							delBills.add(bill);
							bill.setOptions(null);
							billDao.destory(bill);
						}
					}
					//仅需按月份单独开票的发票
					else if(!containsId(ids,bill.getId())&containsId(idmons,bill.getId())){
						//根据月份分类
						Map<String,List<BillOption>> map=new HashMap<String, List<BillOption>>();
						for(BillOption bo:bill.getOptions()){
							if(map.containsKey(bo.getMonth())){
								map.get(bo.getMonth()).add(bo);
							}else{
								List<BillOption> options = new ArrayList<BillOption>();
								options.add(bo);
								map.put(bo.getMonth(), options);
							}
						}
						Bill tmp;
						
						//循环添加
						if(map.size() > 1){
							for(String mon : map.keySet() ){
								tmp = new Bill(bill, map.get(mon));
								newBills.add(tmp);
							}
							
							//删除Bill
							delBills.add(bill);
							bill.setOptions(null);
							billDao.destory(bill);
						}
					}
					// 既按月份，又按金融机构单独开票的发票(每条明细都是一张发票)
					else if(containsId(ids,bill.getId())&&containsId(idmons,bill.getId())){
						Bill tmp;
						List<BillOption>tmpList;
						//循环添加
						for(BillOption option : bill.getOptions() ){
							tmpList=new ArrayList<BillOption>();
							tmpList.add(option);
							tmp = new Bill(bill,tmpList);
							newBills.add(tmp);
						}
						
						//删除Bill
						delBills.add(bill);
						bill.setOptions(null);
						billDao.destory(bill);
					
					}
				}
				
			}
			
			for(Bill b:delBills){//移除已经删除的发票
				apply.getBills().remove(b);
			}
			apply.getBills().addAll(newBills);//添加需要新增的发票
		}
		
		apply.setStatus(BillStatus.APPLYED);
		apply.setApplyDate(new Date());
		billDao.changeStatus(apply.getId(), BillStatus.APPLYED);
		optionDao.changeStatus(apply.getId(), BillStatus.APPLYED);
		submitApply(apply);
	}
	
	//主要是更改状态
		public void submitApply(BillApply apply){
			List<Bill> bills=apply.getBills();
			if(bills!=null){
				for(Bill bill:bills){
					if(bill.getReceivableAmount()==null||bill.getReceivableAmount()==0){
						bill.setReceivableAmount(0d);
						bill.setStatus(BillStatus.OPENED);
						bill.setBillNum("系统默认开票");
						bill.setBillName("系统默认开票");
						bill.setOpenDate(new Date());
					}else{
						bill.setStatus(BillStatus.APPLYED);
					}
					List<BillOption>options=bill.getOptions();
					if(options!=null){
						Map<String,List<BillOption>> map=new HashMap<String, List<BillOption>>();
						for(BillOption option:options){
							if(option.getStatus().getIndex()<bill.getStatus().getIndex()){
								option.setStatus(bill.getStatus());
							}
							if(map.containsKey(option.getFinancial().getName())){
								map.get(option.getFinancial().getName()).add(option);
							}else{
								List<BillOption> l=new ArrayList<BillOption>();
								l.add(option);
								map.put(option.getFinancial().getName(), l);
							}
						}
						//构建发票备注
						StringBuilder sb=new StringBuilder();
						for(String key:map.keySet()){
							sb.append(key).append(":");
							double d=0.0;
							for(BillOption tmp:map.get(key)){
								sb.append(getIntMonth(tmp.getMonth())).append("月 ");
								d+=tmp.getAmount();
							}
							sb.append(d).append(";");
						}
						bill.setBillRemark(sb.toString());
					}
					
				}
			}
			super.save(apply);
		}
	//删除发票明细
	public void delBillOption(Long billOptionId){
		BillOption op= optionDao.get(billOptionId);
		List<Bill> bills=op.getBills();
		if(bills!=null){
			Bill bill=bills.get(0);
			bill.setReceivableAmount(bill.getReceivableAmount()-op.getAmount());
			billDao.save(bill);
		}
		optionDao.destory(billOptionId);
	}
	
	public void delBillOptions(List<BillOption> billOptions){
		if(billOptions == null){
			return ;
		}
		
		for (BillOption billOption : billOptions) {
			delBillOption(billOption.getId());
		}

	}
	
	//删除一组发票明细(季度、半年)
	public void delBillOptionByGroup(String group){
		List<BillOption> ops= optionDao.findBy("group", group);
		Bill bill=null;
		double d=0D;
		if(ops!=null&&ops.size()>0){
			List<Bill> bills=ops.get(0).getBills();
			if(bills!=null&&bills.size()>0)
				bill=bills.get(0);
			for(BillOption op:ops){
				d+=op.getAmount();
				optionDao.destory(op);
			}
		}
		if(bill!=null){
			bill.setReceivableAmount(bill.getReceivableAmount()-d);
			billDao.save(bill);
		}
		
	}

	//申请单
	public List<Object[]> view(Long applyId){
		return applyDao.view(applyId);
	}
	public List<Object[]> view(Long applyId,int pageNo, int pageSize){
		return applyDao.view(applyId,pageNo,pageSize);
	}
	
	//查询该店、金融机构，预收情况中哪些是不该收费的.该收费的改为 应收。
	public List<BillOption> getErrorMonths(Treaty treaty){
		List<BillOption> rus=new ArrayList<BillOption>();
		//只有按月 而且单证释放价=0才会出现预收
		if("0".equals(treaty.getCollectionWay())&&(treaty.getUnitPrice()==null||treaty.getUnitPrice()==0D)){
			
			//查询月份小于当前月的预收
			List<BillOption> all=optionDao.findAdvanceOption(treaty.getFinancial().getId(), treaty.getShop().getId());
			for(BillOption bo:all){
				if(check(treaty, bo.getMonth())){
					bo.setAdvance(false);
					optionDao.save(bo);
				}else{
					rus.add(bo);
				}
			}
			
		}
		return rus;
	}
	//查询该店、金融机构，预收情况中哪些是不该收费的.该收费的改为 应收。=----------------------金融机构
		public List<BillOption> getErrorMonthsFianl(Treaty treaty){
			List<BillOption> rus=new ArrayList<BillOption>();
			//只有按月 而且单证释放价=0才会出现预收
			if("0".equals(treaty.getCollectionWay())&&(treaty.getUnitPrice()==null||treaty.getUnitPrice()==0D)){
				
				//查询月份小于当前月的预收
				List<BillOption> all=optionDao.findAdvanceOption(treaty.getFinancial().getId(), treaty.getShop().getId());
				for(BillOption bo:all){
					if(check(treaty, bo.getMonth())){
						bo.setAdvance(false);
						optionDao.save(bo);
					}else{
						rus.add(bo);
					}
				}
				
			}
			return rus;
		}
	
	/**
	 * 查询需要缴费的月份
	 * @param treaty 协议
	 * @param current是否包含当前月
	 * @return
	 * @throws ParseException 
	 */
	public String[] getMonths(Treaty treaty,boolean current) throws ParseException{
		//按季度:自协议生效月份起(含),从最大收费月份至上一个月中间   满3个月则收费.按季度一定是连续的
		//按半年:自协议生效月份起(含),从最大收费月份至上一个月中间   满6个月则收费.按半年一定是连续的
		//按月:自协议生效月份起(含),至今  所有未缴费的月份,月份可能有间隔。
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM");
		
		String start=sdf.format(treaty.getStartDate());
		String toMonth=sdf.format(new Date());
		String preMonth=DateUtil.getPreMonth(toMonth);
		String months[]=null,rus[]=null;
		if("0".equals(treaty.getCollectionWay())){
			if(treaty.getUnitPrice()==null||treaty.getUnitPrice()==0D){
				months=DateUtil.getBetweenMonthAry(start, toMonth);
			}else
				months=DateUtil.getBetweenMonthAry(start, preMonth);
		}else if("1".equals(treaty.getCollectionWay())){//按季度
			months=getMonths(start, preMonth, 3);
		}else{//按半年
			months=getMonths(start, preMonth, 6);
		}
		if(months!=null&&months.length>0){
			List<String> list=optionDao.findAdvanceMonths(treaty.getFinancial().getId(), treaty.getShop().getId(), start, months[months.length-1]);
			ArrayList<String> all=new ArrayList<String>(Arrays.asList(months));
			for(String s:list){
				if(all.contains(s))
					all.remove(s);
			}
			rus=CommonUtil.listToArray(all);
		}
		return rus;
	}
	
	/**
	 * 获取季度/半年 可以收取的月份
	 * @param treaty 协议
	 * @return
	 * @throws ParseException 
	 */
	public String[] getShMonths(Treaty treaty) throws ParseException{
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM");
		
		String start=sdf.format(treaty.getStartDate());//协议开始时间
		String end=sdf.format(treaty.getEndDate());//协议结束时间
		
		String months[]=null,rus[]=null;
		months=DateUtil.getBetweenMonthAry(start, end);//获得协议的所有月份区间
		//排除已经收取的月份
		if(months!=null&&months.length>0){
			List<String> list=optionDao.findAdvanceMonths(treaty.getFinancial().getId(), treaty.getShop().getId(), start,end);
			ArrayList<String> all=new ArrayList<String>(Arrays.asList(months));
			for(String s:list){
				if(all.contains(s))
					all.remove(s);
			}
			rus=CommonUtil.listToArray(all);
		}
		return rus;
	}
	
	/**
	 * 查询需要缴费的月份--金融机构  不会包含当月的数据
	 * @param treaty 协议
	 * @return
	 * @throws ParseException 
	 */
	public String[] getMonths(Treaty treaty) throws ParseException{
		//按季度:自协议生效月份起(含),从最大收费月份至上一个月中间   满3个月则收费.按季度一定是连续的
		//按半年:自协议生效月份起(含),从最大收费月份至上一个月中间   满6个月则收费.按半年一定是连续的
		//按月:自协议生效月份起(含),至今  所有未缴费的月份,月份可能有间隔。
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM");
		
		String start=sdf.format(treaty.getStartDate());
		String toMonth=sdf.format(new Date());
		String preMonth=DateUtil.getPreMonth(toMonth);
		String months[]=null,rus[]=null;
		if("0".equals(treaty.getCollectionWay())){
				months=DateUtil.getBetweenMonthAry(start, preMonth);
		}else if("1".equals(treaty.getCollectionWay())){//按季度
			months=getMonths(start, preMonth, 3);
		}else{//按半年
			months=getMonths(start, preMonth, 6);
		}
		if(months!=null&&months.length>0){
			List<String> list=optionDao.findAdvanceMonths(treaty.getFinancial().getId(), treaty.getShop().getId(), start, months[months.length-1]);
			ArrayList<String> all=new ArrayList<String>(Arrays.asList(months));
			for(String s:list){
				if(all.contains(s))
					all.remove(s);
			}
			rus=CommonUtil.listToArray(all);
		}
		return rus;
	}
	
	//按季度、按半年 去掉多余的月份
	public String[] getMonths(String start,String preMonth,int n) throws ParseException{
		String mons[] =DateUtil.getBetweenMonthAry(start, preMonth);
		if(null == mons){
			return null;
		}
		int len=mons.length;
		if(len%n!=0){
			len=len-(len%n);
		}
		String months[]=new String[len];
		System.arraycopy(mons, 0, months, 0, len);
		return months;
	}
	
	//查询发车日期，看该月是否应该收费
	public boolean check(Treaty treaty,String month){
		int c=cfService.findCertificationInMonth(treaty.getFinancial().getId(), treaty.getShop().getId(), month);
		if(c==0)
			return false;
		return true;
	}
	//查询发车日期，看该月是否应该收费------------------金融机构
		public boolean checkFianl(Treaty treaty,String month,String isnotOpenBill,String isOpenmoneyStockBill,String isOpenReleteBill){
			int maxt =0;
			if(isnotOpenBill != null && isnotOpenBill.equals("0")){//根据发车信息确定
				 maxt=cfService.findCertificationInMonth(treaty.getFinancial().getId(), treaty.getShop().getId(), month);
			}
			if(isOpenReleteBill != null && isOpenReleteBill.equals("1")){//根据释放确定
				 maxt=cfService.findReleaseCertificationInMonth(treaty.getFinancial().getId(), treaty.getShop().getId(), month);
			}
			if (isOpenmoneyStockBill != null && isOpenmoneyStockBill.equals("2")){//根据在库信息来收取
				 maxt=cfService.finCertifcatiionInQtyBill( treaty.getShop().getId(),treaty.getFinancial().getId(), month);
			}
			if(maxt == 0)
				return false;
			else 
				return true;
		}
	/**
	 * 获得驻店员的名字
	 * @param id
	 * @return
	 */
	public String findUserShopByShopName(Long id){
		String name = "";
		List<Organization> organizations = organizationService.findUserShopByShopId(id);//
		if(organizations != null && organizations.size()>0){
			for(Organization organization : organizations){
				name = name + organization.getName() + "  ";
			}
		}
		return name;
	}
	/**
	 * 获得区域经理的名字
	 * @param id
	 * @return
	 */
	public String findUserDomainByShopName(Long id){
		String name = "";
		List<Organization> organizations = organizationService.findUserDomainByShopId(id);//
		if(organizations != null && organizations.size()>0){
			for(Organization organization : organizations){
				name = name + organization.getName() + "  ";
			}
		}
		return name;
	}
	/**
	 * 获得指定日期内的释放数
	 * @param finId
	 * @param shopId
	 * @param month
	 * @return
	 */
	public int findReleaseCertificationInMonth(Long finId,Long shopId,String month){
		return cfService.findReleaseCertificationInMonth(finId, shopId, month);
	}
	
	/**
	 * 删除管理费申请
	 * @param id
	 */
	public void delete(Long id){
		
		BillApply apply=super.find(id);
		List<Bill> bills=apply.getBills();
		List<BillOption> options = new ArrayList<BillOption>();
		for(Bill bill:bills){
			options.addAll(bill.getOptions());
			billDao.destory(bill);
		}
		BillOption tmpOption=null;
		for(BillOption op:options){
			try {
				if(op.getMoveId()!=null){
					tmpOption=optionDao.find(op.getMoveId());
					if(tmpOption!=null){
						tmpOption.setMonth(op.getMonth());
						optionDao.save(tmpOption);
					}
				}
			} catch (ObjectNotFoundException e) {
			}
			optionDao.destory(op);
		}
		super.destory(apply);
		
	}
	
	public List<Financial> getFins(Long applyId){
		return applyDao.getFins(applyId);
	}
	
	//获得整数月份
	private static String getIntMonth(String month){
		if(CommonUtil.isNotEmpty(month)&&month.length()==7){
			String tmp=month.substring(5, 7);
			Integer m=Integer.parseInt(tmp);
			return m.toString();
		}
		return null;
	}
	
	private boolean containsId(List<Long>list,Long id){
		if(CommonUtil.isEmptyList(list)||id==null)
			return false;
		return list.contains(id);
	}
}
